package com.nanbei.a02;



import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.CommonAnnotationBeanPostProcessor;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;


/**
 * @ClassDescription: BeanFactory的实现
 * @JdkVersion: 1.8
 * @Author: libs
 * @Created: 2024/9/6 15:45
 */
public class TestBeanFactory {
    public static void main(String[] args)  {

        // DefaultListableBeanFactory 是 Spring 最常见的 BeanFactory 实现，允许你注册、管理、销毁 Bean，并提供了非常丰富的功能。
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // bean 的定义 （class  ,scope  ,初始化方法 ,销毁方法）            generic(通用)
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition(Config.class)
                .setScope(BeanDefinition.SCOPE_SINGLETON).getBeanDefinition();

        //将一个名为 "config" 的 Bean 定义注册到 DefaultListableBeanFactory 实例中
        beanFactory.registerBeanDefinition("config",beanDefinition);
        // 获取bean 定义的名称
        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

        /** =====================       添加bean工厂后置处理器       ============================= */

        // 给 beanFactory 添加一些常用的后处理器
        /*
        AnnotationConfigUtils.registerAnnotationConfigProcessors 的作用是注册以下几种常用的注解处:
            AutowiredAnnotationBeanPostProcessor：处理 @Autowired 注解，自动将依赖注入到 Bean 的字段、方法或构造函数中。
            CommonAnnotationBeanPostProcessor：处理 JSR-250 注解，如 @PostConstruct、@PreDestroy 和 @Resource。
            RequiredAnnotationBeanPostProcessor：处理标记了 @Required 注解的 Bean 属性，确保这些属性必须被注入。
         */
        //  Annotation 注解   register 注册  Processor 处理器
        AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

        // 获取bean 定义的名称
        beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }


        // BeanFactory 后处理器主要功能，补充了一些bean的定义
        // getBeansOfType(BeanFactoryPostProcessor.class)：这个方法会返回一个 Map，其中键是 Bean 的名称，
        //          值是 BeanFactoryPostProcessor 类型的 Bean 实例。
        //          这样，Spring 会找到所有实现了 BeanFactoryPostProcessor 接口的 Bean 并返回给你。
        beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values().forEach(beanFactoryPostProcessor -> {
            // 执行bean工厂后置处理器
            beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
        });

        // 执行后处理器之后  查看有哪些bean
        beanDefinitionNames = beanFactory.getBeanDefinitionNames();
        System.out.println("-------------------------------------");
        for (String beanDefinitionName : beanDefinitionNames) {
            System.out.println(beanDefinitionName);
        }

        // 获取bean1  发现 bean2 并未注入到bean1中
        // System.out.println(beanFactory.getBean(Bean1.class).getBean2());

        /** =====================       添加 bean 后置处理器       ============================= */


        // bean的后处理器 针对bean 的生命周期的个个阶段提供扩展 例如 @Autowired @Resource...
        // 建立bean工厂和后置处理器的联系
        // 将bean的后置处理器添加到Bean工厂中，在getBean的时候就会进入到bean的生命周期，进入bean的生命周期后就会调用bean的后置处理器
        beanFactory.getBeansOfType(BeanPostProcessor.class).values()
                //.stream().sorted(beanFactory.getDependencyComparator())
                .forEach(beanPostProcessor->{
            System.out.println(">>>" + beanPostProcessor);
            if (beanPostProcessor.getClass().equals(AutowiredAnnotationBeanPostProcessor.class)){
                AutowiredAnnotationBeanPostProcessor beanPostProcessor1 = (AutowiredAnnotationBeanPostProcessor) beanPostProcessor;
                System.out.println(beanPostProcessor1.getOrder());
            }
            if (beanPostProcessor.getClass().equals(CommonAnnotationBeanPostProcessor.class)){
                CommonAnnotationBeanPostProcessor beanPostProcessor1 = (CommonAnnotationBeanPostProcessor) beanPostProcessor;
                System.out.println(beanPostProcessor1.getOrder());
            }
            beanFactory.addBeanPostProcessor(beanPostProcessor);
        });


        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        // 获取bean1  发现 bean2 注入到bean1中
        //System.out.println(beanFactory.getBean(Bean1.class).getBean2());

        // 创建好所有的单例对象
        beanFactory.preInstantiateSingletons();
        System.out.println("===================================================");
        //System.out.println(beanFactory.getBean(Bean1.class).getBean2());
        System.out.println(beanFactory.getBean(Bean1.class).getInter());

        /*
            学到了什么:
                a.beanFactory 不会做的事
                    1.不会主动调用 BeanFactory 后处理器
                    2.不会主动添加 Bean 后处理器
                    3.不会主动初始化单例
                    4.不会解析beanFactory 还不会解析${}与#{}
                b.bean 后处理器会有排序的逻辑
         */


    }

    @Configuration
    static class Config{
        @Bean
        public Bean1 bean1(){
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(){
            return new Bean2();
        }

        @Bean
        public Bean3 bean3(){
            return new Bean3();
        }

        @Bean
        public Bean4 bean4(){
            return new Bean4();
        }
    }

    interface Inter{
        void prV();
    }

    static class Bean3 implements Inter{

        @Override
        public void prV() {
            System.out.println("");
        }
    }

    static class Bean4 implements Inter{

        @Override
        public void prV() {
            System.out.println("");
        }
    }

    static class Bean1{

        private final Logger logger = LoggerFactory.getLogger(Bean1.class);

        public Bean1() {
            logger.info("构造bean1()");
        }

        @Autowired
        public Bean2 bean2;


        public Bean2 getBean2() {
            return bean2;
        }

        // 当@Autowired  @Resource  注解同时使用的话， @Autowired 因为优先级比较高所以会先生效，
        @Autowired
        @Resource(name = "bean4")
        private Inter bean3;

        public Inter getInter() {
            return bean3;
        }
    }


    static class Bean2{
        private final Logger logger = LoggerFactory.getLogger(Bean2.class);

        public Bean2() {
            logger.info("构造bean2()");
        }
    }
}
